#include "connection.h"
#include "threadSafeQueue.h"

#include "log.h"
#include "opcode2name.h"

Socket* GetSocket::SocketInstance(SocketType socketType)
{
	Socket* instance = NULL;

#ifdef WIN32
	instance = SAFE_NEW SocketWin(socketType);
#elif defined(LINUX)
	instance = SAFE_NEW SocketLinux(socketType);
#endif

	return instance;
}

Connection::Connection(SocketType socketType, int socket)
: m_bIsAliveInSocket(true)
{
	m_socket = GetSocket::SocketInstance(socketType);
	m_socket->CreateSocket(socket);
}

Connection::~Connection()
{
	SAFE_DELETE(m_socket);
}

void Connection::Disconnect()
{
	m_mutex.Lock();

	if(m_socket->GetSocket() > 0)
	{
		m_socket->CloseSocket();
		ClosePacket();
	}
	
	m_mutex.Unlock();
}

bool Connection::IsAlive()
{
	if(m_socket == NULL)
		return false;

	m_mutex.Lock();
	bool bIsAlive = m_socket->GetSocket() > 0;
	m_mutex.Unlock();

	return bIsAlive;
}

bool Connection::Recv()
{
	char buffer[ONLINE_MAX_PACKET_SIZE] = { 0 };

	char* data = buffer;
	int size = ONLINE_MAX_PACKET_SIZE;
	if(!m_socket->Recv(data, size))
		Disconnect();
	else
	{
		if(size == 0)
			Disconnect();
		else if(size > 0)
			m_recvBuffer.append(buffer, size);
	}

	if(size < ONLINE_MAX_PACKET_SIZE || m_recvBuffer.size() > ONLINE_MAX_PACKET_SIZE)
		return true;
	else
		return false;
}

void Connection::RecvSelect()
{	
	while(recv_select())
	{
		if(Recv())
			break;
	}
}

bool Connection::Send(const string& data)
{
	return Send(data.c_str(), data.size());
}

bool Connection::Send(const char* buffer, size_t size)
{
	size_t sendSize = 0;
	while(sendSize < size)
	{
		int len = size - sendSize;
		if(m_socket->Send(buffer + sendSize, len))
			sendSize += len;
		else
		{
			Disconnect();
			return false;
		}
	}

	return true;
}

bool Connection::SendSelect(const string& data)
{
	if(send_select())
		return Send(data);

	return false;
}

bool Connection::SendSelect(const char* buffer, size_t size)
{	
	if(send_select())
		return Send(buffer, size);

	return false;
}